home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / mus / edit / amisox_wav.lha / rate.c < prev    next >
C/C++ Source or Header  |  1992-03-27  |  5KB  |  181 lines

  1.  
  2. /*
  3.  * July 5, 1991
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Sound Tools rate change effect file.
  13.  */
  14.  
  15. #include "st.h"
  16. #include <math.h>
  17.  
  18. /*
  19.  * Least Common Multiple Linear Interpolation 
  20.  *
  21.  * Find least common multiple of the two sample rates.
  22.  * Construct the signal at the LCM by interpolating successive
  23.  * input samples as straight lines.  Pull output samples from
  24.  * this line at output rate.
  25.  *
  26.  * Of course, actually calculate only the output samples.
  27.  *
  28.  * LCM must be 32 bits or less.  Two prime number sample rates
  29.  * between 32768 and 65535 will yield a 32-bit LCM, so this is 
  30.  * stretching it.
  31.  */
  32.  
  33. /*
  34.  * Algorithm:
  35.  *  
  36.  *  Generate a master sample clock from the LCM of the two rates.
  37.  *  Interpolate linearly along it.  Count up input and output skips.
  38.  *
  39.  *  Input:   |inskip |       |       |       |       |
  40.  *                                                                      
  41.  *                                                                      
  42.  *                                                                      
  43.  *  LCM:     |   |   |   |   |   |   |   |   |   |   |
  44.  *                                                                      
  45.  *                                                                      
  46.  *                                                                      
  47.  *  Output:  |  outskip  |           |           | 
  48.  *
  49.  *                                                                      
  50.  */
  51.  
  52.  
  53. /* Private data for Lerp via LCM file */
  54. typedef struct ratestuff {
  55.     u_l    lcmrate;        /* least common multiple of rates */
  56.     u_l    inskip, outskip;    /* LCM increments for I & O rates */
  57.     u_l    total;
  58.     u_l    intot, outtot;        /* total samples in terms of LCM rate */
  59.     long    lastsamp;
  60. } *rate_t;
  61.  
  62. /*
  63.  * Process options
  64.  */
  65. rate_getopts(effp, n, argv) 
  66. eff_t effp;
  67. int n;
  68. char **argv;
  69. {
  70.     if (n)
  71.         fail("Rate effect takes no options.");
  72. }
  73.  
  74. /*
  75.  * Prepare processing.
  76.  */
  77. rate_start(effp)
  78. eff_t effp;
  79. {
  80.     rate_t rate = (rate_t) effp->priv;
  81.     
  82.     rate->lcmrate = lcm(effp->ininfo.rate, effp->outinfo.rate);
  83.     /* Cursory check for LCM overflow.  
  84.      * If both rate are below 65k, there should be no problem.
  85.      * 16 bits x 16 bits = 32 bits, which we can handle.
  86.      */
  87. /*
  88.     This is bogus, need a test for 32-bit overflow.
  89.  
  90.     if ((rate->lcmrate / gcd(effp->ininfo.rate, effp->outinfo.rate)) !=
  91.         (effp->ininfo.rate * effp->outinfo.rate))
  92. fprintf(stderr, "Rate effect: Least Common Multiple overflowed!\n");
  93. */
  94.     rate->inskip = rate->lcmrate / effp->ininfo.rate;
  95.     rate->outskip = rate->lcmrate / effp->outinfo.rate; 
  96.     rate->total = rate->intot = rate->outtot = 0;
  97.     rate->lastsamp = 0;
  98. }
  99.  
  100. /*
  101.  * Processed signed long samples from ibuf to obuf.
  102.  * Return number of samples processed.
  103.  */
  104.  
  105. rate_flow(effp, ibuf, obuf, isamp, osamp)
  106. eff_t effp;
  107. long *ibuf, *obuf;
  108. int *isamp, *osamp;
  109. {
  110.     rate_t rate = (rate_t) effp->priv;
  111.     int len, done;
  112.     int skip;
  113.     long *istart = ibuf;
  114.     long last;
  115.     
  116.     char c;
  117.     unsigned char uc;
  118.     short s;
  119.     unsigned short us;
  120.     long l;
  121.     unsigned long ul;
  122.     float f;
  123.     double d;
  124.  
  125.     done = 0;
  126.     if (rate->total == 0) {
  127.         /* Emit first sample.  We know the fence posts meet. */
  128.         *obuf = *ibuf++;
  129.         /* Count up until have right input samples */
  130.             rate->lastsamp = *obuf++ >> 16;
  131.         done = 1;
  132.         rate->total = 1;
  133.         /* advance to second output */
  134.         rate->outtot += rate->outskip;
  135.         /* advance input range to span next output */
  136.         while ((rate->intot + rate->inskip) <= rate->outtot){
  137.             last = *ibuf++ / 65536;
  138.             rate->intot += rate->inskip;
  139.         }
  140.     }
  141.     /* number of output samples the input can feed */
  142.     len = (*isamp * rate->inskip) / rate->outskip;
  143.     if (len > *osamp)
  144.         len = *osamp;
  145.     last = rate->lastsamp;
  146.     for(; done < len; done++) {
  147.         *obuf = last;
  148.         *obuf += ((float)((*ibuf / 65536)  - last)* ((float)rate->outtot - 
  149.                 rate->intot))/rate->inskip;
  150.         *obuf *= 65536;
  151.         obuf++;
  152.         /* advance to next output */
  153.         rate->outtot += rate->outskip;
  154.         /* advance input range to span next output */
  155.         while ((rate->intot + rate->inskip) <= rate->outtot){
  156.             last = *ibuf++ >> 16;
  157.             rate->intot += rate->inskip;
  158.             if (ibuf - istart == *isamp)
  159.                 goto out;
  160.         }
  161.         /* long samples with high LCM's overrun counters! */
  162.         if (rate->outtot == rate->intot)
  163.             rate->outtot = rate->intot = 0;
  164.     }
  165. out:
  166.     *isamp = ibuf - istart;
  167.     *osamp = len;
  168.     rate->lastsamp = last;
  169. }
  170.  
  171. /*
  172.  * Do anything required when you stop reading samples.  
  173.  * Don't close input file! 
  174.  */
  175. rate_stop(effp)
  176. eff_t effp;
  177. {
  178.     /* nothing to do */
  179. }
  180.  
  181.